package {
	
	import flash.utils.Proxy;
	import flash.utils.flash_proxy;
	
	/**
	 * A sample associative array with a working
	 * length property.
	 */
	dynamic public class AssociativeArray extends Proxy {
		
		private var memberValueHash:Object = new Object();
		private var memberIndexHash:Object = new Object();
		private var memberNameArray:Array = new Array();
			
		public function get length():uint {
			return memberNameArray.length;
		}
		override flash_proxy function setProperty(name:*, value:*):void {
			if (name in memberValueHash == false) {
				var last:uint = memberNameArray.length;
				memberIndexHash[name] = last;
				memberNameArray[last] = name;
			}
			memberValueHash[name] = value;
		}
		override flash_proxy function getProperty(name:*):* {
			return memberValueHash[name];
		}
		override flash_proxy function callProperty(name:*, ...rest):* {
			if (memberValueHash[name] is Function){
				return memberValueHash[name].apply(null, arguments);
			}
			return null;
		}
		override flash_proxy function hasProperty(name:*):Boolean {
			return name in memberValueHash;
		}
		override flash_proxy function deleteProperty(name:*):Boolean {
			if (name in memberValueHash){
				var index:int = memberIndexHash[name];
				memberNameArray.splice(index, 1);
				var last:uint = memberNameArray.length;
				while(index < last){
					memberIndexHash[memberNameArray[index]]--;
					index++;
				}
				delete memberValueHash[name];
				delete memberIndexHash[name];
				return true;
			}
			return false;
		}
		override flash_proxy function nextNameIndex(index:int):int {
			return (index < memberNameArray.length) ? index + 1 : 0;
		}
		override flash_proxy function nextName(index:int):String {
			return memberNameArray[index - 1];
		}
		override flash_proxy function nextValue(index:int):* {
			return memberValueHash[memberNameArray[index - 1]];
		}
		override flash_proxy function getDescendants(name:*):* {
			return null;
		}
		override flash_proxy function isAttribute(name:*):Boolean {
			return false;
		}
	}
}